/////////////////////////////////////////////////////////////////////////////////////
// Include Files
#include "MeshManager.h"
#include "MeshAsset.h"

//// INLINE GALLEON MESH FILE HACK
//#include "..\Blockade\Meshes\Galleon.mesh"

/* TODO
 * models are instanced into the scene, textures, shaders, and animations are associated with each instance
 * any number of textures can be attached with no limitations
 * only one shader can be attached, and it must have a matching vertex declaration
 * any number of animations may be attached:
 *     for skeletal animation, you must link up the bones of the animation to the bones of the model
 *     for morphing animation, you must link up the vertices of the animation to the vertices of the model
 * if the shader uses more textures than are attached, a checkerboard is used for the remainder (issue warning)
 * if the shader uses less textures than are attached, the remainder are ignored (issue warning)
 *
 *
 *
 * vertex types (in directx style?), (from flux), these are used in meshes and shaders...
 *
 * static F3DVertexElement RenderVertexElem[] = {
 *     { 0, offsetof(RenderVertex, x),		F3DDECLTYPE_FLOAT3,		F3DDECLMETHOD_DEFAULT,	F3DDECLUSAGE_POSITION,	0 },
 *     { 0, offsetof(RenderVertex, u),		F3DDECLTYPE_FLOAT2,		F3DDECLMETHOD_DEFAULT,	F3DDECLUSAGE_TEXCOORD,	0 },
 *     { 0, offsetof(RenderVertex, color),	F3DDECLTYPE_UBYTE4N,	F3DDECLMETHOD_DEFAULT,	F3DDECLUSAGE_COLOR,		0 },
 *     F3DDECL_END() // == { 0xFF, 0, F3DDECLTYPE_UNUSED, 0, 0, 0 }
 * };
 *
 * { stream_number, element_offset, data_type, tessellation_method, usage, usage_index }
 *
 * my version, modified from the one above:
 * removed stream_number for now, but it could be useful when optimizing, for example for water only the position changes, it can be kept in a separate stream
 * removed tessellation_method, I'll get into that when I'm ready for tessellation...
 * CE_DECLUSAGE needs to have a straight correspondence to the 16 inputs, also include CE_DECLUSAGE_0 - CE_DECLUSAGE_15
 * usage_index... ???... took it out
 *
 * VertexDecl RenderVertexDecl(3);
 * RenderVertexDecl[0] = VertexElem( 0,  CE_DECLTYPE_FLOAT3, CE_DECLUSAGE_POSITION );
 * RenderVertexDecl[1] = VertexElem( 12, CE_DECLTYPE_FLOAT2, CE_DECLUSAGE_TEXCOORD );
 * RenderVertexDecl[2] = VertexElem( 20, CE_DECLTYPE_BYTE4N, CE_DECLUSAGE_COLOR    ); <--- BYTE4N: 4 bytes are normalized by dividing by 255
 */
//
//enum decltype_t
//{
//	DECLTYPE_FLOAT1, 
//	DECLTYPE_FLOAT2, 
//	DECLTYPE_FLOAT3, 
//	DECLTYPE_FLOAT4, 
//
//	DECLTYPE_FLOAT1N, 
//	DECLTYPE_FLOAT2N, 
//	DECLTYPE_FLOAT3N, 
//	DECLTYPE_FLOAT4N, 
//};
//
//enum declusage_t
//{
//	DECLUSAGE_0, 
//	DECLUSAGE_1, 
//	DECLUSAGE_2, 
//	DECLUSAGE_3, 
//	DECLUSAGE_4, 
//	DECLUSAGE_5, 
//	DECLUSAGE_6, 
//	DECLUSAGE_7, 
//	DECLUSAGE_8, 
//	DECLUSAGE_9, 
//	DECLUSAGE_10, 
//	DECLUSAGE_11, 
//	DECLUSAGE_12, 
//	DECLUSAGE_13, 
//	DECLUSAGE_14, 
//	DECLUSAGE_15, 
//
//	DECLUSAGE_POSITION  = DECLUSAGE_0, 
//	DECLUSAGE_NORMAL    = DECLUSAGE_1, 
//	DECLUSAGE_AMBIENT   = DECLUSAGE_2, 
//	DECLUSAGE_DIFFUSE   = DECLUSAGE_3, 
//	DECLUSAGE_SPECULAR  = DECLUSAGE_4, 
//	DECLUSAGE_MISC0     = DECLUSAGE_5, 
//	DECLUSAGE_MISC1     = DECLUSAGE_6, 
//	DECLUSAGE_MISC2     = DECLUSAGE_7, 
//	DECLUSAGE_TEXCOORD0 = DECLUSAGE_8, 
//	DECLUSAGE_TEXCOORD1 = DECLUSAGE_9, 
//	DECLUSAGE_TEXCOORD2 = DECLUSAGE_10, 
//	DECLUSAGE_TEXCOORD3 = DECLUSAGE_11, 
//	DECLUSAGE_TEXCOORD4 = DECLUSAGE_12, 
//	DECLUSAGE_TEXCOORD5 = DECLUSAGE_13, 
//	DECLUSAGE_TEXCOORD6 = DECLUSAGE_14, 
//	DECLUSAGE_TEXCOORD7 = DECLUSAGE_15, 
//};

/////////////////////////////////////////////////////////////////////////////////////
// CMeshManager Implementation
void IE::CMeshManager::Initialize()
{
}

void IE::CMeshManager::Shutdown()
{
}

//void CMeshManager::LoadMeshFile( string_t _strFilename )
//{
//	MeshLoad.Raise( new CMeshEventArg(_strFilename) );
//}
//
//void CMeshManager::CreateMesh( CMeshEventArg &_rArg )
//{
//	string_t _strFilename = _rArg.GetName();
//
//	TMesh mesh;
//	mesh.strName = _strFilename;
//
//	glGenVertexArrays(1, &mesh.uiVAO);
//	glBindVertexArray(mesh.uiVAO);
//
//	// HACK HACK OMG HACK SO MUCH HACK IT BURNS OH FUCK IT HURTS
//	if( _strFilename == L"..\\Blockade\\Meshes\\Galleon.mesh" )
//	{
//		/* all the information below needs to go in a file:
//		 * 
//		 * index buffer:
//		 *     uint32 - index data type
//		 *     uint32 - index count
//		 *     uint32 - usage
//		 *     byte[] - index buffer
//		 * 
//		 * vertex buffer:
//		 *     uint32 - number of bytes in vertex buffer
//		 *     uint32 - usage
//		 *     byte[] - vertex buffer
//		 * 
//		 * vertex attributes:
//		 *     uint32 - number of vertex attributes
//		 *     attribute[]
//		 *         uint32 - index
//		 *         uint32 - size
//		 *         uint32 - type
//		 *         uint32 - normalized
//		 *         uint32 - stride
//		 *         uint32 - offset
//		 */
//
//		// vertex buffer
//		mesh.uiVBO = CreateBuffer( GL_ARRAY_BUFFER, 
//			g_uiVertexCount * sizeof(float_t), g_pVertexData, GL_STATIC_DRAW );
//
//		// index buffer
//		mesh.uiIBO = CreateBuffer( GL_ELEMENT_ARRAY_BUFFER, 
//			g_uiIndexCount * sizeof(uint16_t), g_pIndexData, GL_STATIC_DRAW );
//
//		// vertex attributes
//		glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 36, (void*)0);
//		glEnableVertexAttribArray(0);
//
//		glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 36, (void*)12);
//		glEnableVertexAttribArray(1);
//
//		glVertexAttribPointer(2, 3, GL_FLOAT, GL_TRUE, 36, (void*)24);
//		glEnableVertexAttribArray(2);
//
//		// drawing data
//		mesh.uiIndexCount  = g_uiIndexCount;
//		mesh.eIndexType    = GL_UNSIGNED_SHORT;
//	}
//	else if( _strFilename == L"..\\Blockade\\Meshes\\Sky.mesh" )
//	{
//		float_t arrVertices[8][3];
//		arrVertices[0][0] =  1.00f; arrVertices[0][1] =  1.00f; arrVertices[0][2] = -1.00f;
//		arrVertices[1][0] = -1.00f; arrVertices[1][1] =  1.00f; arrVertices[1][2] =  1.00f;
//		arrVertices[2][0] = -1.00f; arrVertices[2][1] =  1.00f; arrVertices[2][2] = -1.00f;
//		arrVertices[3][0] =  1.00f; arrVertices[3][1] =  1.00f; arrVertices[3][2] =  1.00f;
//		arrVertices[4][0] =  1.00f; arrVertices[4][1] = -1.00f; arrVertices[4][2] =  1.00f;
//		arrVertices[5][0] = -1.00f; arrVertices[5][1] = -1.00f; arrVertices[5][2] = -1.00f;
//		arrVertices[6][0] = -1.00f; arrVertices[6][1] = -1.00f; arrVertices[6][2] =  1.00f;
//		arrVertices[7][0] =  1.00f; arrVertices[7][1] = -1.00f; arrVertices[7][2] = -1.00f;
//
//		uint8_t arrIndices[36];
//		arrIndices[ 0] = 0; arrIndices[ 1] = 2; arrIndices[ 2] = 1;
//		arrIndices[ 3] = 3; arrIndices[ 4] = 0; arrIndices[ 5] = 1;
//		arrIndices[ 6] = 4; arrIndices[ 7] = 6; arrIndices[ 8] = 5;
//		arrIndices[ 9] = 7; arrIndices[10] = 4; arrIndices[11] = 5;
//		arrIndices[12] = 3; arrIndices[13] = 1; arrIndices[14] = 6;
//		arrIndices[15] = 4; arrIndices[16] = 3; arrIndices[17] = 6;
//		arrIndices[18] = 7; arrIndices[19] = 5; arrIndices[20] = 2;
//		arrIndices[21] = 0; arrIndices[22] = 7; arrIndices[23] = 2;
//		arrIndices[24] = 1; arrIndices[25] = 2; arrIndices[26] = 5;
//		arrIndices[27] = 6; arrIndices[28] = 1; arrIndices[29] = 5;
//		arrIndices[30] = 0; arrIndices[31] = 3; arrIndices[32] = 4;
//		arrIndices[33] = 7; arrIndices[34] = 0; arrIndices[35] = 4;
//
//		// vertex buffer
//		mesh.uiVBO = CreateBuffer( GL_ARRAY_BUFFER, 
//			8 * 3 * sizeof(float_t), arrVertices, GL_STATIC_DRAW );
//		// = uiBuffer;
//
//		// index buffer
//		mesh.uiIBO = CreateBuffer( GL_ELEMENT_ARRAY_BUFFER, 
//			36 * sizeof(uint8_t), arrIndices, GL_STATIC_DRAW );
//
//		// vertex attributes
//		glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 12, (void*)0);
//		glEnableVertexAttribArray(0);
//
//		// drawing data
//		mesh.uiIndexCount = 36;
//		mesh.eIndexType = GL_UNSIGNED_BYTE;
//	}
//	else if( _strFilename == L"..\\Blockade\\Meshes\\Water.mesh" )
//	{
//		struct Vert
//		{
//			float_t pos[3];
//			float_t tex0[2];
//			float_t tex1[2];
//		};
//
//		Vert arrVertices[101][101];
//		for( int_t x = 0; x < 101; ++x )
//		{
//			for( int_t z = 0; z < 101; ++z )
//			{
//				float_t fX = (50.0f - x) * 10.0f;
//				float_t fZ = (50.0f - z) * 10.0f;
//
//				arrVertices[x][z].pos[0] = fX;
//				arrVertices[x][z].pos[1] = 0.0f;
//				arrVertices[x][z].pos[2] = fZ;
//
//				arrVertices[x][z].tex0[0] = fX / 200.0f;
//				arrVertices[x][z].tex0[1] = fZ / 200.0f;
//
//				arrVertices[x][z].tex1[0] = fX / 50.0f;
//				arrVertices[x][z].tex1[1] = fZ / 50.0f;
//			}
//		}
//
//		uint32_t arrIndices[60000];
//		uint32_t uiVert = 0;
//		for( uint32_t x = 0; x < 100; ++x )
//		{
//			for( uint32_t z = 0; z < 100; ++z )
//			{
//				arrIndices[uiVert++] = (x + 0) * 101 + (z + 0);
//				arrIndices[uiVert++] = (x + 1) * 101 + (z + 0);
//				arrIndices[uiVert++] = (x + 1) * 101 + (z + 1);
//				arrIndices[uiVert++] = (x + 0) * 101 + (z + 0);
//				arrIndices[uiVert++] = (x + 1) * 101 + (z + 1);
//				arrIndices[uiVert++] = (x + 0) * 101 + (z + 1);
//			}
//		}
//
//		// vertex buffer
//		mesh.uiVBO = CreateBuffer( 
//			GL_ARRAY_BUFFER, 10201 * sizeof(Vert), 
//			arrVertices, GL_DYNAMIC_DRAW 
//			);
//
//		// index buffer
//		mesh.uiIBO = CreateBuffer( 
//			GL_ELEMENT_ARRAY_BUFFER, 60000 * sizeof(uint32_t), 
//			arrIndices, GL_STATIC_DRAW 
//			);
//
//		// vertex attributes
//		glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vert), (void*)0);
//		glEnableVertexAttribArray(0);
//
//		glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(Vert), (void*)12);
//		glEnableVertexAttribArray(1);
//
//		glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vert), (void*)20);
//		glEnableVertexAttribArray(2);
//
//		// drawing data
//		mesh.uiIndexCount = 60000;
//		mesh.eIndexType = GL_UNSIGNED_INT;
//	}
//	else
//	{
//		assert(false);
//	}
//	m_lstMeshes.Append(mesh);
//}
//
//void CMeshManager::UpdateMesh( CMeshEventArg &_rArg )
//{
//	// get the mesh
//	TMesh *pMesh = GetMesh(_rArg.GetName());
//
//	// TODO: currently this is depending on the fact that the water is the only 
//	//     mesh that updates and that it will always be updating its vertex buffer
//
//	// update the vertex buffer
//	glBindBuffer( GL_ARRAY_BUFFER, pMesh->uiVBO );
//	void *pMap = glMapBuffer( GL_ARRAY_BUFFER, GL_WRITE_ONLY );
//	memcpy(pMap, _rArg.GetVertexData(), _rArg.GetVertexDataSize());
//	glUnmapBuffer(GL_ARRAY_BUFFER);
//}
//
//uint_t CMeshManager::CreateBuffer( GLenum _eTarget, uint_t _uiSize, void *_pData, GLenum _eUsage )
//{
//	// create the buffer
//	uint_t uiBuffer;
//	glGenBuffers( 1, &uiBuffer );
//	glBindBuffer( _eTarget, uiBuffer );
//	glBufferData( _eTarget, _uiSize, _pData, _eUsage );
//	return uiBuffer;
//}
